import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.Socket;
import java.util.*;

public class Client {

    //tracker的ip以及udoport必须配置
    public static String trackerIP ="localhost";
    public static String trackerPort ="6000";



    private static Socket socket;
    public static Player me;
    public static String myName;
    public static Map<String, Player> map = new HashMap<>();
    public static String serverIP;// = "localhost";
    public static String saveServerIP;// = "localhost";

    public static  byte minX;
    public static byte maxX;
    public static byte minY;
    public static byte maxY;


    public static String saveServerUdpPort;// = "6666";
    public static String serverTcpPort;// = "6666";



    public static int ID = new Random().nextInt(1000);

    public static void main(String[] args) throws IOException {


        try {
            //来自用户的命令
            //函数封装了检错等所有功能
            while (true) {
                String s = "";
                synchronized (new Object()) {
                    System.out.print("command>");
                    s = new Scanner(System.in).nextLine();
                }
                String[] s1 = s.split(" ");
                if (me == null && !s1[0].equals("login")) {
                    System.out.println("请先使用login登录");
                    System.out.print("command>");
                }
                if (s1[0].equals("login")) {
                    if (s1.length == 1) {
                        System.out.println("参数不合法");
                        System.out.print("command>");
                        continue;
                    }
                    //步骤1：udp获得serverIP 和 saveServerUdpPort  及一些边界条件
                    System.out.println("步骤1：发送给tracker获得serverIP 和 saveServerUdpPort");
                    int res = storage_location_request(s1[1].trim());
                    if(res==-1)//说明udp出错或者服务器出错了
                    {
                        break;
                    }
                    myName=s1[1].trim();
                    System.out.println("步骤2：发送给server获得name对应的player信息");
                    //步骤2：此时获得服务器消息之后  向服务器获取name对应的player信息
                    res=player_state_request(s1[1].trim());
                    if(res==-1)//说明udp出错或者服务器出错了
                    {
                        break;
                    }

                    System.out.println("步骤3：发个tacker 通过已获得的x，y向tracker获得服务器的tcp端口号");
                    //步骤3：此时获得了me的消息   通过x，y向tracker获得服务器的tcp端口号
                    res=server_area_request();
                    if(res==-1)//说明udp出错或者服务器出错了
                    {
                        break;
                    }

                    loginRequest();
                } else if (s1[0].equals("move")) {
                    if (s1.length == 1) {
                        System.out.println("参数不合法");
                        System.out.print("command>");
                        continue;
                    }
                    //先移动  然后判断区域
                    if (s1[1].trim().equals("east")) //east
                    {
                        me.x += 3;
                    }
                    else if (s1[1].trim().equals("west")) //west
                    {
                        me.x -= 3;
                    }
                    if(!(minX<=me.x&&me.x<=maxX))
                    {
                        if(me.x<=0)
                            me.x+=100;
                        me.x%=100;
                        System.out.println("超出区域！！此时位置应该为为("+me.x+","+me.y+")");
                        logout();
                        //此时获得了me的消息   通过x，y向tracker获得服务器的tcp端口号
                        int res=server_area_request();
                        if(res==-1)//说明udp出错或者服务器出错了
                        {
                            break;
                        }

                        loginRequest();
                        continue;
                    }

                    //如果不超出区域  还原之前的移动操作
                    if (s1[1].equals("east")) //east
                    {
                        me.x -= 3;
                    } else if (s1[1].equals("west")) //west
                    {
                        me.x += 3;
                    }

                    move(s1[1].trim());
                } else if (s1[0].equals("attack")) {
                    if (s1.length == 1) {
                        System.out.println("参数不合法");
                        System.out.print("command>");
                        continue;
                    }
                    attack(s1[1]);
                } else if (s1[0].equals("speak")) {
                    if (s1.length == 1) {
                        System.out.println("参数不合法");
                        System.out.print("command>");
                        continue;
                    }
                    String msg = "";
                    for (int i = 1; i < s1.length; i++)
                        msg += s1[i];
                    speak(msg);
                } else if (s1[0].equals("logout")) {
                    save_state_request();
                    logout();
                    me = null;
                    map = new HashMap<>();
                    socket = new Socket(serverIP, Integer.parseInt(serverTcpPort));
                } else {
                    System.out.println("命令不合法，请重新输入");
                    System.out.print("command>");
                }
            }
        } catch (Exception e) {
            System.out.println("The gate to the tiny world of warcraft has disappeared.");
        }

    }

    public static void logout() throws IOException {
        OutputStream os = socket.getOutputStream();
        byte[] bytes = new byte[4];//固定长度4个字节
        bytes[0] = 4;//第一行固定
        bytes[1] = 0;
        bytes[2] = 4;
        bytes[3] = 9;
        os.write(bytes);
    }

    public static void speak(String msg) throws IOException {
        byte[] bytes1 = msg.getBytes();
        if (bytes1.length > 255) {
            System.out.println("输入的消息过长");
            System.out.print("command>");
            return;
        }
        //msg最大长度为255字节
        int paddings = 4 - (bytes1.length + 1) % 4;//paddings最后    此处的加1表示\0
        int length = bytes1.length + paddings + 4 + 1;
        byte[] temp = new byte[4];
        temp[3] = (byte) (length >> 24);
        temp[2] = (byte) (length >> 16);
        temp[1] = (byte) (length >> 8);
        temp[0] = (byte) length;


        OutputStream os = socket.getOutputStream();
        byte[] bytes = new byte[length];//长度1
        bytes[0] = 4;//第一行固定
        bytes[1] = temp[1];//temp[1]是高位   temp[0]是低位
        bytes[2] = temp[0];
        bytes[3] = 7;

        //此处拼接msg进去
        for (int i = 0; i < bytes1.length; i++) {
            bytes[4 + i] = bytes1[i];
        }
        bytes[4 + bytes1.length] = 0;//此处固定为\0即固定值为0

        //最后固定为padding
        for (int i = 0; i < paddings; i++) {
            bytes[4 + bytes1.length + 1 + i] = 0;
        }

        os.write(bytes);
    }

    public static void attack(String name) throws IOException {
        if (map.containsKey(name)) {
            Player player = map.get(name);
            //攻击的人在是视野内
            if (me.x - player.x >= -5 && me.x - player.x <= 5 && me.y - player.y >= -5 && me.y - player.y <= 5) {
                OutputStream os = socket.getOutputStream();
                byte[] bytes = name.trim().getBytes();

                byte[] bytes1 = new byte[16];
                bytes1[0] = 4;
                bytes1[1] = 0;
                bytes1[2] = 16;
                bytes1[3] = 5;

                for (int i = 0; i < name.length(); i++)
                    bytes1[4 + i] = bytes[i];

                for (int i = 4 + name.length(); i < 16; i++)
                    bytes1[i] = 0;

                os.write(bytes1);
            } else//攻击的人不在视野内
            {
                System.out.println("The target is not visible");
                System.out.print("command>");
            }
        } else {
            System.out.println("攻击的人不存在");
            System.out.print("command>");
        }


    }

    public static void move(String name) throws IOException {
        byte direction;
        if (name.equals("north"))
            direction = 0;
        else if (name.equals("south"))
            direction = 1;
        else if (name.equals("east"))
            direction = 2;
        else if (name.equals("west"))
            direction = 3;
        else {
            System.out.println("输入的方位不正确");
            System.out.print("command>");
            return;
        }


        OutputStream os = socket.getOutputStream();
        byte[] bytes = new byte[8];//固定长度8个字节
        bytes[0] = 4;//第一行固定
        bytes[1] = 0;
        bytes[2] = 8;
        bytes[3] = 3;

        bytes[4] = direction;
        bytes[5] = 0;
        bytes[6] = 0;
        bytes[7] = 0;
        os.write(bytes);
    }

    public static void loginRequest() throws IOException {
        byte[] bytes1 = me.name.getBytes();
        if (bytes1.length > 9) {
            System.out.println("输入的名字过长");
            System.out.print("command>");
            return;
        }
        OutputStream os = socket.getOutputStream();
        byte[] bytes = new byte[24];//固定长度24个字节
        bytes[0] = 4;//第一行固定
        bytes[1] = 0;
        bytes[2] = 24;
        bytes[3] = 1;

        byte[] bytes2 = Arrays.copyOf(bytes1, 10);
        //此处拼接name进去
        for (int i = 0; i < 10; i++) {
            bytes[4 + i] = bytes2[i];
        }

        byte[] bytes3 = toBytes(me.hp);
        bytes[14] = bytes3[0];
        bytes[15] = bytes3[1];
        bytes[16] = bytes3[2];
        bytes[17] = bytes3[3];

        byte[] bytes4 = toBytes(me.exp);
        bytes[18] = bytes4[0];
        bytes[19] = bytes4[1];
        bytes[20] = bytes4[2];
        bytes[21] = bytes4[3];

        bytes[22] = (byte) me.x;
        bytes[23] = (byte) me.y;
//        System.out.println("loginRequest:"+Arrays.toString(bytes));
        os.write(bytes);
    }

    static class Player {
        public String name;
        public int hp;
        public int exp;
        public int x;
        public int y;

        public Player() {
        }

        public Player(String name, int hp, int exp, int x, int y) {
            this.name = name;
            this.hp = hp;
            this.exp = exp;
            this.x = x;
            this.y = y;
        }

        @Override
        public String toString() {
            return "Player{" +
                    "name='" + name + '\'' +
                    ", hp=" + hp +
                    ", exp=" + exp +
                    ", x=" + x +
                    ", y=" + y +
                    '}';
        }
    }

    //客户端向服务器发送消息，以存储玩家的状态
    public static int save_state_request() throws IOException {
        byte[] bytes = new byte[28];
        bytes[0] = 6;//msgType

        byte[] bytes2 = toBytes(ID);

        bytes[1] = bytes2[0];//唯一id
        bytes[2] = bytes2[1];
        bytes[3] = bytes2[2];
        bytes[4] = bytes2[3];

        int count = 5;
        byte[] bytes1 = Arrays.copyOf(me.name.getBytes(), 10);
        for (byte b : bytes1) {
            bytes[count++] = b;
        }
        byte[] bytes3 = toBytes(me.hp);
        for (byte b : bytes3) {
            bytes[count++] = b;
        }
        byte[] bytes4 = toBytes(me.exp);
        for (byte b : bytes4) {
            bytes[count++] = b;
        }
        bytes[count++] = (byte) me.x;
        bytes[count++] = (byte) me.y;

        //客户端发送消息给tracker，请求指定玩家所对应的服务器的地址
        byte[] data1 =new byte[1024];//接收到的数据
        int i = 0;
        for (; i < 4; i++) {
            InetAddress inetAddress =InetAddress.getByName(saveServerIP);
            DatagramPacket dp = new DatagramPacket(bytes,bytes.length,inetAddress,Integer.parseInt(saveServerUdpPort));
            DatagramSocket ds = new DatagramSocket();
            ds.send(dp);

            DatagramPacket dp1 = new DatagramPacket(data1,data1.length);
            ds.setSoTimeout((int) (100*Math.pow(2,i)));
            try {
                ds.receive(dp1);
            }catch (IOException e)
            {
                //如果超时  直接continue重新发送
                continue;
            }
            //如果没有超时

            int recvID = toInt(Arrays.copyOfRange(data1, 1, 5));
            if(ID==recvID)
                break;
            ds.close();
        }
        if(i==4)//接收消息失败
        {
            System.out.println("udp没有接收到save_state_response");
            return -1;
        }
        //接收消息成功  才能运行到这里  此时数据都在data1中
        ID++;/**************每当接收到消息之后id都要自增******************/

        int code=data1[6];
//        if(code==0)
//            System.out.println("存储数据成功");
        if(code==1)
        {
            System.out.println("存储数据失败");
            System.out.print("command>");
        }

        return 0;
    }


    //客户端发送给服务器获得指定玩家的状态
    public static int player_state_request(String name) throws IOException {
        byte[] bytes = new byte[16];
        bytes[0] = 4;//msgType

        byte[] bytes2 = toBytes(ID);

        bytes[1] = bytes2[0];//唯一id
        bytes[2] = bytes2[1];
        bytes[3] = bytes2[2];
        bytes[4] = bytes2[3];

        int count = 5;
        byte[] bytes1 = Arrays.copyOf(name.getBytes(),10);
        for (byte b : bytes1) {
            bytes[count++] = b;
        }


        //客户端发送消息给tracker，请求指定玩家所对应的服务器的地址
        byte[] data1 =new byte[1024];//接收到的数据
        int i = 0;
        for (; i < 4; i++) {
            InetAddress inetAddress =InetAddress.getByName(saveServerIP);
            DatagramPacket dp = new DatagramPacket(bytes,bytes.length,inetAddress,Integer.parseInt(saveServerUdpPort));
            DatagramSocket ds = new DatagramSocket();
            ds.send(dp);

            DatagramPacket dp1 = new DatagramPacket(data1,data1.length);
            ds.setSoTimeout((int) (100*Math.pow(2,i)));
            try {
                ds.receive(dp1);
            }catch (IOException e)
            {
                //如果超时  直接continue重新发送
                continue;
            }
            //如果没有超时

            int recvID = toInt(Arrays.copyOfRange(data1, 1, 5));
            if(ID==recvID)
                break;
            ds.close();
        }
        if(i==4)//接收消息失败
        {
            System.out.println("udp没有接收到player_state_response");
            return -1;
        }
        //接收消息成功  才能运行到这里
        //解析STORAGE_LOCATION_RESPONSE  此时数据都在data1中
        ID++;/**************每当接收到消息之后id都要自增******************/

        String getName=new String(Arrays.copyOfRange(data1,5,15)).trim();
        int getHP=toInt(Arrays.copyOfRange(data1,15,19));
        int getEXP=toInt(Arrays.copyOfRange(data1,19,23));
        me=new Player(getName,getHP,getEXP,data1[23],data1[24]);
        System.out.println("udp向服务器获得玩家状态"+me);
        return 0;
    }

    //客户机向tracker发送请求以获得某个位置所对应的服务器
    public static int server_area_request() throws IOException {
        byte[] bytes = new byte[8];
        bytes[0] = 2;//msgType

        byte[] bytes2 = toBytes(ID);

        bytes[1] = bytes2[0];//唯一id
        bytes[2] = bytes2[1];
        bytes[3] = bytes2[2];
        bytes[4] = bytes2[3];

        bytes[5] = (byte) me.x;
        bytes[6] = (byte) me.y;
        bytes[6] = 0;//padding

        //客户端发送消息给tracker，请求指定玩家所对应的服务器的地址
        byte[] data1 =new byte[1024];//接收到的数据
        int i = 0;
        for (; i < 4; i++) {
            InetAddress inetAddress =InetAddress.getByName(trackerIP);
            DatagramPacket dp = new DatagramPacket(bytes,bytes.length,inetAddress,Integer.parseInt(trackerPort));
            DatagramSocket ds = new DatagramSocket();
            ds.send(dp);

            DatagramPacket dp1 = new DatagramPacket(data1,data1.length);
            ds.setSoTimeout((int) (100*Math.pow(2,i)));
            try {
                ds.receive(dp1);
            }catch (IOException e)
            {
                //如果超时  直接continue重新发送
                continue;
            }
            //如果没有超时

            int recvID = toInt(Arrays.copyOfRange(data1, 1, 5));
            if(ID==recvID)
                break;
            ds.close();
        }
        if(i==4)//接收消息失败
        {
            System.out.println("udp没有接收到server_area_response");
            return -1;
        }
        //接收消息成功  才能运行到这里  此时数据都在data1中
        ID++;/**************每当接收到消息之后id都要自增******************/

        serverIP=""+Byte.toUnsignedInt(data1[5])+"."+Byte.toUnsignedInt(data1[6])+"."
                +Byte.toUnsignedInt(data1[7])+"."+Byte.toUnsignedInt(data1[8]);
        serverTcpPort=""+(Byte.toUnsignedInt(data1[9])*Math.pow(2,8)+Byte.toUnsignedInt(data1[10]));
        serverTcpPort= serverTcpPort.split("\\.")[0];
        minX=data1[11];
        maxX=data1[12];
        minY=data1[13];
        maxY=data1[14];

        System.out.println("收到的serverIP "+serverIP+" serverTcpPort "+ serverTcpPort+" minX:"+minX+" maxX:"+maxX);
        try {
            socket = new Socket(serverIP, Integer.parseInt(serverTcpPort));
            System.out.println(socket);
            new Thread(new MyRunnable()).start();//接收来自服务器的消息
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("The gate to the tiny world of warcraft is not ready.");
            return -1;
        }
        return 0;
    }

    //客户端发送消息给tracker，请求指定玩家所对应的服务器的地址
    public static int storage_location_request(String name) throws IOException {
        byte[] bytes = new byte[16];
        bytes[0] = 0;//msgType


        byte[] bytes2 = toBytes(ID);

        bytes[1] = bytes2[0];//唯一id
        bytes[2] = bytes2[1];
        bytes[3] = bytes2[2];
        bytes[4] = bytes2[3];

        int count = 5;
        byte[] bytes1 = Arrays.copyOf(name.getBytes(),10);
        for (byte b : bytes1) {
            bytes[count++] = b;
        }

        //客户端发送消息给tracker，请求指定玩家所对应的服务器的地址
        byte[] data1 =new byte[1024];//接收到的数据
        int i = 0;
        for (; i < 4; i++) {
            InetAddress inetAddress =InetAddress.getByName(trackerIP);
            DatagramPacket dp = new DatagramPacket(bytes,bytes.length,inetAddress,Integer.parseInt(trackerPort));
            DatagramSocket ds = new DatagramSocket();
            ds.send(dp);

            DatagramPacket dp1 = new DatagramPacket(data1,data1.length);
            ds.setSoTimeout((int) (100*Math.pow(2,i)));
            try {
                ds.receive(dp1);
            }catch (IOException e)
            {
                //如果超时  直接continue重新发送
                continue;
            }
            //如果没有超时

            int recvID = toInt(Arrays.copyOfRange(data1, 1, 5));
            if(ID==recvID)//如果等到想要的消息
                break;
            ds.close();
        }
        if(i==4)//接收消息失败
        {
            System.out.println("udp没有接收到storage_location_response");
            return -1;
        }
        //接收消息成功  才能运行到这里
        //解析STORAGE_LOCATION_RESPONSE  此时数据都在data1中
        ID++;/**************每当接收到消息之后id都要自增******************/

        saveServerIP=""+Byte.toUnsignedInt(data1[5])+"."+Byte.toUnsignedInt(data1[6])+"."
                +Byte.toUnsignedInt(data1[7])+"."+Byte.toUnsignedInt(data1[8]);
        saveServerUdpPort =""+toInt(Arrays.copyOfRange(data1,9,13));

        System.out.println("收到的saveServerIP "+saveServerIP+" saveServerUdpPort "+ saveServerUdpPort);
        return 0;
    }



    public static int toInt(byte[] bytes) {//把长度为4的bytes数组转化为int
        return Byte.toUnsignedInt(bytes[0]) * (int) Math.pow(2, 24) +
                Byte.toUnsignedInt(bytes[1]) * (int) Math.pow(2, 16) +
                Byte.toUnsignedInt(bytes[2]) * (int) Math.pow(2, 8) +
                Byte.toUnsignedInt(bytes[3]);
    }

    public static byte[] toBytes(int a) {
        byte[] temp = new byte[4];
        temp[0] = (byte) (a >> 24);
        temp[1] = (byte) (a >> 16);
        temp[2] = (byte) (a >> 8);
        temp[3] = (byte) a;
        return temp;
    }

    static class MyRunnable implements Runnable {


        @Override
        public void run() {
            while (true) {
                try {
                    try {
                        socket.sendUrgentData(0xFF);
                    } catch (Exception e) {
                        System.out.println("Meteor is striking the world.");
                        break;
                    }
                    InputStream is = socket.getInputStream();
                    byte[] bytes = new byte[4];
                    is.read(bytes);//读取第一行的消息头
                    int length = Byte.toUnsignedInt(bytes[1]) * (int) Math.pow(2, 8)
                            + Byte.toUnsignedInt(bytes[2]);

                    if (bytes[3] == 2)//LOGIN_REPLY消息
                    {
                        byte[] bytes1 = new byte[1];
                        is.read(bytes1);
                        if (bytes1[0] == 0)//登录成功
                        {
                            System.out.println("Welcome to the tiny world of warcraft.");
                            System.out.print("command>");
                            //打印  HP EXP 方位  等消息
                            byte[] bytes2 = new byte[4];
                            byte[] bytes3 = new byte[4];
                            is.read(bytes2);
                            is.read(bytes3);
                            int HP = toInt(bytes2);
                            int EXP = toInt(bytes3);
                            byte xy[] = new byte[3];//读3的原因是最有一个字节的padding
                            is.read(xy);
                            int X = xy[0];
                            int Y = xy[1];
                            System.out.print("location=(" + X + "," + Y + ")");
                            System.out.print(" HP:" + HP);
                            System.out.println(" EXP:" + EXP);
                            System.out.print("command>");
                            me = new Player(myName, HP, EXP, X, Y);
                            map.put(me.name, me);
                        }
                        if (bytes1[0] == 1) {//已有人登录
                            is.read(new byte[11]);//读取padding
                            System.out.println("A play with the same name is already in the game.");
                            System.out.print("command>");
                        }
                    }
                    if (me == null) //如果为空   不接收消息
                        continue;
                    if (bytes[3] == 4)//MOVE_NOTIFY消息
                    {
                        byte[] bytes1 = new byte[10];
                        is.read(bytes1);//读取name
                        String name = new String(bytes1).trim();

                        byte[] xy = new byte[2];
                        is.read(xy);//读取坐标
                        byte[] bytes2 = new byte[4];
                        byte[] bytes3 = new byte[4];
                        is.read(bytes2);
                        is.read(bytes3);
                        int HP = toInt(bytes2);
                        int EXP = toInt(bytes3);

                        if (name.equals(me.name)) {
                            me.exp = EXP;
                            me.hp = HP;
                            me.x = xy[0];
                            me.y = xy[1];

                            //如果自己被杀复活  会收到moveNotify消息  此时判断在哪个区域中
                            if(!(minX<=me.x&&me.x<=maxX))
                            {
                                System.out.println("重生时超出区域！！此时位置为("+me.x+","+me.y+")");
                                logout();
                                //此时获得了me的消息   通过x，y向tracker获得服务器的tcp端口号
                                int res=server_area_request();
                                if(res==-1)//说明udp出错或者服务器出错了
                                {
                                    break;
                                }
                                loginRequest();
                                continue;
                            }
                        }

                        //如果在map中  则更新数据
                        if (map.containsKey(name)) {//因为初始登录的时候  会获得所有玩家的movenotify
                            Player player = map.get(name);
                            player.hp = HP;
                            player.exp = EXP;
                            player.x = xy[0];
                            player.y = xy[1];
                        } else//如果不在map中  put进去
                        {
                            map.put(name, new Player(name, HP, EXP, xy[0], xy[1]));
                        }


                        if (name.equals(me.name))//如果是自己移动以   则输出自己的位置
                        {
                            System.out.println("我的位置：" + me.name + ":location=("
                                    + me.x + "," + me.y + ")," + "HP="
                                    + me.hp + "," + "EXP=" + me.exp + "   ");
                            System.out.print("command>");

                            //每次接受到和自己有关的movenotify  都请求saveServer保存
                            save_state_request();
                        }

                        //任何人的移动   都可能导致我进入别人视野  或者别人进入我的视野
                        int tag = 0;
                        for (String s : map.keySet()) {
                            if (s.equals(me.name))
                                continue;
                            //在可视范围内
                            Player player = map.get(s);
                            if (me.x - player.x >= -5 && me.x - player.x <= 5 && me.y - player.y >= -5 && me.y - player.y <= 5) {
                                if (tag == 0) {
                                    System.out.println("视野范围内：");
                                    System.out.print("command>");
                                    tag = 1;
                                }
                                System.out.println(player.name + ":location=("
                                        + player.x + "," + player.y + ")," + "HP="
                                        + player.hp + "," + "EXP=" + player.exp + "   ");
                                System.out.print("command>");
                            }
                        }
                    }


                    if (bytes[3] == 6)//ATTACT_NOTIFY消息
                    {
                        byte[] bytes1 = new byte[10];
                        is.read(bytes1);//读取attackerName
                        String attackerName = new String(bytes1).trim();

                        byte[] bytes2 = new byte[10];
                        is.read(bytes2);//读取victimName
                        int t = 0;
                        for (int i = 0; i < bytes2.length; i++)
                            if (bytes2[i] == 0) {
                                t = i;
                                break;
                            }
                        String victimName = new String(Arrays.copyOfRange(bytes2, 0, t + 1)).trim();

                        byte[] bytes3 = new byte[1];
                        is.read(bytes3);//读取Damage
                        byte damage = bytes3[0];

                        byte[] bytes6 = new byte[4];
                        is.read(bytes6);
                        int HP = toInt(bytes6);

                        byte[] bytes4 = new byte[3];
                        is.read(bytes4);//读取padding

                        //输出对话
                        /***************需要过滤消息******************/
                        if (me.x - map.get(victimName).x >= -5 && me.x - map.get(victimName).x <= 5 && me.y - map.get(victimName).y >= -5 && me.y - map.get(victimName).y <= 5) {
                            if (me.x - map.get(attackerName).x >= -5 && me.x - map.get(attackerName).x <= 5 && me.y - map.get(attackerName).y >= -5 && me.y - map.get(attackerName).y <= 5) {
                                System.out.println(attackerName.trim() + "对" + victimName.trim() + "造成了" + damage + "点伤害");
                                System.out.print("command>");
                            }
                        }
                        if (HP == 0) {
                            System.out.println(attackerName + " killed " + victimName);
                            System.out.print("command>");
                        }

                        if(attackerName.trim().equals(me.name))
                        {
                            me.exp+=damage;
                            save_state_request();
                        }
                    }
                    if (bytes[3] == 8)// SPEAK_NOTIFY消息
                    {
//                        System.out.println("进入SPEAK_NOTIFY消息");
                        byte[] bytes1 = new byte[10];
                        is.read(bytes1);//读取发送消息的人名
                        String sayName = new String(bytes1).trim();
                        byte[] bytes2 = new byte[length - 4 - 10];
                        is.read(bytes2);//读出剩下的所有消息
                        //static byte[] copyOf(byte[] original, int newLength)
                        int end = 0;
                        for (int i = bytes2.length - 1; i >= 0; i--)
                            if (bytes2[i] != 0) {
                                end = i;
                                break;
                            }
                        byte[] bytes3 = Arrays.copyOf(bytes2, end + 1);
                        String msg = new String(bytes3).trim();
                        System.out.println(sayName + ": " + msg);
                        System.out.print("command>");
                    }
                    if (bytes[3] == 10)//logoutNotify
                    {
                        byte[] bytes1 = new byte[10];
                        is.read(bytes1);
                        String logoutName = new String(bytes1).trim();

                        byte[] bytes3 = new byte[4];
                        is.read(bytes3);
                        int logoutIP = toInt(bytes3);
                        byte[] bytes4 = new byte[4];
                        is.read(bytes4);
                        int logoutEXP = toInt(bytes4);

                        int logoutX=is.read();
                        int logoutY=is.read();


                        System.out.println("Player " + logoutName + " has left the tiny world of warcraft.");
                        System.out.print("command>");
                    }
                    if (bytes[3] == 11)//无效消息
                    {
                        byte[] bytes1 = new byte[4];
                        is.read(bytes1);
                        if (bytes1[0] == 0)
                            System.out.println("You must log in first.");
                        if (bytes1[0] == 1)
                            System.out.println("You already logged in.");
                        System.out.print("command>");
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("Meteor is striking the world.");
                    break;
                }
            }
        }
    }
}
